﻿using System.Reflection;
using System;
using GeneralTool.CoreLibrary.Extensions;
using GeneralTool.CoreLibrary.Interfaces;
using GeneralTool.CoreLibrary.TaskLib;

namespace GeneralTool.CoreLibrary.IniHelpers
{
    /// <summary>
    /// 简单的Ini管理
    /// </summary>
    public class SimpleIniManager
    {
        /// <summary>
        /// Ini路径
        /// </summary>
        public string IniPath { get; private set; }

        /// <summary>
        /// Ini对象
        /// </summary>
        public IniHelper IniHelper { get; private set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="iniPath">ini文件保存路径,如果为null,则默认生成ini文件到输出目录下Configs/default.ini文件</param>
        public SimpleIniManager(string iniPath = null)
        {
            this.IniPath = iniPath;
            this.IniHelper = IniHelper.GetInstace(iniPath);
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="sectionName">标题名称</param>
        /// <param name="key">键名</param>
        /// <returns>返回值</returns>
        public virtual string GetValue(string sectionName, string key)
        {
            return this.IniHelper.GetString(sectionName, key, "");
        }

        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="sectionName"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public virtual void SetValue(string sectionName, string key, string value)
        {
            this.IniHelper.WriteValueString(sectionName, key, value);
        }

        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="sectionName"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public virtual void SetValue(string sectionName, string key, object value, Type type = null, bool isJosn = false, IJsonConvert jsonConvert = null)
        {
            SetValue(this.IniHelper, sectionName, key, value, type, isJosn, jsonConvert);
        }

        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="sectionName"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetValue(IniHelper iniHelper, string sectionName, string key, object value, Type type = null, bool isJosn = false, IJsonConvert jsonConvert = null)
        {
            //this.IniHelper.WriteValueString(sectionName, key, value + "");
            if (type == null)
            {
                if (string.IsNullOrWhiteSpace(value + ""))
                    throw new Exception("当type给予null时,value不可为null");

                type = value.GetType();
            }
            if (isJosn)
            {
                //转换为Json,查看有无Json转换器

                string jsonStr = SerializeToString(jsonConvert, value);
                iniHelper.WriteValueString(sectionName, key, jsonStr);

                return;
            }
            if (type.IsGenericType || type.IsArray)
            {
                //获取长度
                int len = 0;
                MethodInfo get = null;
                if (type.IsGenericType)
                {
                    len = (int)type.GetMethod("get_Count").Invoke(value, null);
                    get = type.GetMethod("get_Item", new Type[] { typeof(int) });
                }
                else if (type.IsArray)
                {
                    len = (int)type.GetMethod("get_Length").Invoke(value, null);
                    get = type.GetMethod("GetValue", new Type[] { typeof(int) });
                }

                // var set = type.GetMethod("SetValue");
                object[] objs = new object[len];
                for (int i = 0; i < len; i++)
                {
                    objs[i] = get.Invoke(value, new object[] { i });
                }
                string val = string.Join(",", objs);
                iniHelper.WriteValueString(sectionName, key, val);
            }
            else if (type.IsEnum)
            {
                iniHelper.WriteValueString(sectionName, key, Convert.ToInt32(value).ToString());
            }
            else
            {
                iniHelper.WriteValueString(sectionName, key, value + "");
            }
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sectionName"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual T GetValue<T>(string sectionName, string key, T @default = default, bool isJosn = false, IJsonConvert jsonConvert = null)
        {
            //return this.IniHelper.GetValue<T>(sectionName, key);
            return (T)GetValue(typeof(T), this.IniHelper, sectionName, key, @default, isJosn, jsonConvert);

        }

        public static object GetValue(Type valueType, IniHelper iniHelper, string sectionName, string key, object @default = default, bool isJosn = false, IJsonConvert jsonConvert = null)
        {
            //获取值
            string tmp = iniHelper.GetValue<string>(sectionName, key);
        
            if (isJosn)
            {
                //转换为Json,查看有无Json转换器
                var obj = DesrializeToObj(jsonConvert, valueType, iniHelper, sectionName, key, @default);

                return obj;
            }

            //如果是泛型或数组类型
            if (valueType.IsGenericType || valueType.IsArray)
            {
                //创建类型
                string[] arr = tmp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                object obj;
                if (valueType.IsGenericType)
                {
                    if (valueType.GenericTypeArguments[0] == typeof(string))
                    {
                        obj = Activator.CreateInstance(valueType, new object[] { arr });
                    }
                    else
                    {
                        obj = Activator.CreateInstance(valueType, new object[] { arr.Length });
                        MethodInfo method = valueType.GetMethod("Add", new Type[] { valueType.GenericTypeArguments[0] });
                        for (int i = 0; i < arr.Length; i++)
                        {
                            _ = method.Invoke(obj, new object[] { Convert.ChangeType(arr[i], valueType.GenericTypeArguments[0]) });
                        }
                    }
                }
                else
                {
                    string assName = valueType.FullName.Replace("[]", string.Empty);
                    Type t = Type.GetType(assName);
                    obj = Activator.CreateInstance(valueType, new object[] { arr.Length });
                    MethodInfo method = valueType.GetMethod("Set", new Type[] { typeof(int), t });
                    for (int i = 0; i < arr.Length; i++)
                    {
                        _ = method.Invoke(obj, new object[] { i, Convert.ChangeType(arr[i], t) });
                    }
                }

                return obj;
            }
            else if (valueType.IsEnum)
            {
                //枚举类型
                try
                {
                    var obj = Enum.Parse(valueType, tmp, true);
                    //先尝试字符串转
                    return obj;
                }
                catch
                {
                    return Enum.ToObject(valueType, tmp);
                }
            }
            else
            {
                return iniHelper.GetValue(sectionName, key, @default, valueType);
            }
        }


        public static object DesrializeToObj(IJsonConvert jsonConvert, Type type, IniHelper iniHelper, string sectionName, string keyName, object @default)
        {
            if (jsonConvert == null)
            {
                jsonConvert = new BaseJsonCovert();
            }
            string value = iniHelper.GetString(sectionName, keyName, GetDefaultValue(jsonConvert, @default));
            object obj = jsonConvert != null ? jsonConvert.DeserializeObject(value, type) : value.DeserializeJsonToObject(type);
            return obj;
        }

        public static string GetDefaultValue(IJsonConvert jsonType, object @default)
        {
            return SerializeToString(jsonType, @default);
        }



        public static string SerializeToString(IJsonConvert jsonConvert, object value)
        {
            string jsonStr = jsonConvert != null ? jsonConvert.SerializeObject(value) : value.SerializeToJsonString();
            return jsonStr;
        }
    }
}
